home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 050 / xrf.arc / XRFM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1986-04-20  |  8.2 KB  |  243 lines

  1. /*
  2.  *                      ***************
  3.  *                      * X R F M . C *
  4.  *                      ***************
  5.  *
  6.  * disk storage routines. To handle large concatanations, when  
  7.  * memory is full, it is necessary to write storage to disk each
  8.  * time, and then take this into account when printing. In effect
  9.  * XRF becomes a primitive polyphase sort.
  10.  *
  11.  * Version V1.17           1-Apr-85 MC    first edition
  12.  * Version V1.18          14-Apr-85 MC    Packed records for workfiles
  13.  *
  14.  * The key is structured as <KEYactualNNNNNNNN> from XRF0.C where:-
  15.  *                     KEY                is the symbol as lower case
  16.  *                                                 length CPS characters.
  17.  *                              actual          is the symbol as she appears
  18.  *                                                 length CPS characters.
  19.  *                          NNNNNNNN  is the program name
  20.  *                                                 length 8 chars
  21.  * Carried with this is the Reference as an integer.
  22.  *
  23.  * version V1.19      25-Apr-85 MC    Use path picked up as from C86TEMP
  24.  *                    which is loaded as SET C86TEMP=
  25.  *                    The most sensible use of this is 
  26.  *                    ramdrive.
  27.  */
  28.  
  29.  
  30. #include <stdio.h>
  31. #include "xrf.h"
  32.  
  33. static struct BUFR wbuf;    /* static buffer as this is for mem full pb */
  34. /*----------------------------------------------------------------*/
  35. /* write tree. Write memory structure to disk, sorted records so  */
  36. /*             merge phase can just collate                       */
  37. /*             Record structure is:-                              */
  38. /*              2 byte record count as int                        */
  39. /*              n byte key 1 as ASCIIZ (max CPS+1)                */
  40. /*             n byte key 1 as ASCIIZ (max CPS+1)                */
  41. /*              n byte key 1 as ASCIIZ (max 8+1)                  */
  42. /*              2 byte reference number as int                    */
  43. /*                                                                */
  44. /* The node is now positioned in the tree in case non-sensitive order.
  45.  * This means that in the final list mixed, upper & lower case symbols
  46.  * appear togethor instead of being separated in the collating sequence.
  47.  *
  48. */
  49. wrtree(ofile,link)
  50. struct dsk *ofile;
  51. struct idt *link;
  52.  
  53. { struct ref *r;              /* Ref chain pointer */
  54.   int ks=2;                     /* size of key */
  55.    if (link != NULL){
  56.       wrtree(ofile,link->left);                    /* Visit the left */
  57.       ks+=wpack(ofile->mdnbuf->b_key,link->keyp);  /* insert key into buffer */
  58.       for(r=link->first;r!=NULL;r=r->next){        /* process ref chain */
  59.     wrput(ofile->mdnfile,&ks,2);               /* Write reclen bytes */
  60.     wrput(ofile->mdnfile,ofile->mdnbuf->b_key,ks-2);
  61.     wrput(ofile->mdnfile,&r->lno,2);           /* Write ref for this one */
  62.     ofile->mdncnt++;
  63.     }
  64.       wrtree(ofile,link->right);                  /* Visit the right */
  65.       }
  66. }
  67. struct dsk *wropen(seqno)        /* open next memory write file */
  68. int seqno;                /* sequence number */
  69. { struct dsk *w;
  70.   char *malloc();
  71.     if((w=(struct dsk *)malloc(sizeof(struct dsk)))==NULL)
  72.     abort("WOPEN no memory\n");
  73.     w->mdnprev=w->mdnnext=NULL;
  74.     w->mdnbuf=&wbuf;
  75.     w->mdneof=w->mdnempty=w->mdncnt=0;
  76.     sprintf(w->mdnfname,"%sXREF%04d.$$$",wpath,seqno);
  77.     if((w->mdnfile=fopen(w->mdnfname,"wb"))==NULL)
  78.     abort("WOPEN can't create %s\n",w->mdnfname);
  79.     return w;
  80. }
  81. wrfix()            /* fix disk chain into place */
  82. { struct dsk *last=NULL, *this=polroot, *temp;
  83.   char *malloc();
  84.     int mcnt=0;
  85.     while (this!=NULL){            /* scan list */
  86.     if(this->mdnfile!=NULL)fclose(this->mdnfile);
  87.     if(this->mdncnt){
  88.        if((this->mdnbuf=(struct BUFR *)malloc(sizeof(struct BUFR)))==NULL)
  89.         quit();  /* I give up *
  90.        if((this->mdnfile=fopen(this->mdnfname,"rb"))==NULL)
  91.         abort("WRFIX can't reopen %s\n",this->mdnfname);
  92.        mcnt++;
  93.        if(verbose)printf("WRFIX Process %s for %9d records\n",
  94.                 this->mdnfname,this->mdncnt);
  95.        this->mdnempty=1;        /* force 'buffer empty' */
  96.        this->mdneof=0;        /* not EOF */
  97.        last=this;
  98.        this=this->mdnnext;        /* go to next */
  99.        this->mdnprev=last;        /* ( and tell it about this one) */
  100.        }
  101.     else {                          /* nought written, lose it */
  102.        unlink(this->mdnfname);
  103.        temp=this;
  104.        if(last!=NULL)this=last->mdnnext=this->mdnnext;
  105.         else this=polroot=this->mdnnext;
  106.        free(temp);
  107.        }
  108.     }
  109.    if(verbose)printf("WRFIX kept %1d memory files\n",mcnt);
  110. }
  111.  
  112. wpack(nk,kp)        /* pack kp->nk returning length in bytes */
  113. char *kp;
  114. char *nk;
  115. { char *tp=nk, *wpackey();
  116.     tp=wpackey(tp,kp,CPS);                   /* key string 1*/
  117.     tp=wpackey(tp,kp+CPS,CPS);               /* key string 2*/
  118.     tp=wpackey(tp,kp+CPS+CPS,8);             /* key string 3*/
  119.     return (int)(tp-nk);
  120. }
  121. char *wpackey(kp,k,len)        /* lose trailing spaces on key, return count */
  122. char *kp;            /* buffer to update */
  123. char k[];            /* input key */
  124. int len;            /* max length of input key */
  125. { int i,stop;
  126.     for(stop=len;stop;stop--)if(k[stop-1]!=' ')break;
  127.     for(i=0;i<stop;*kp++=k[i++]);
  128.     *kp++='\0';
  129.     return kp;
  130. }
  131.  
  132. wrput(f,cp,bytes)
  133. FILE *f;
  134. char *cp;
  135. int bytes;
  136. { int i;
  137.   for(i=0;i<bytes;i++)
  138.     if(fputc(*cp++,f)==EOF)abort("WRPUT Disk full!\n");
  139. }
  140.  
  141. /*-------------------------------------------------------------------*/
  142. /* Merge phase - see if there is a lower key on a disk file compared */
  143. /*               against the current in-core entry.                  */
  144. /*               return NULL if not (memory table is Prime key)      */
  145. struct BUFR *wrmatch(base,node,ref)
  146. struct dsk *base;            /* file linked list base */
  147. struct idt *node;            /* memory node */
  148. struct ref *ref;
  149. { struct dsk *fptr=base, *lowest=NULL;
  150.   int cf, flag=0;
  151.     strcpy(wbuf.b_key,noe->keyp);      /* make memory key in buffer */
  152.     wbuf.b_ref=ref->lno;
  153.     lowest=&wbuf;
  154.     while (fptr!=NULL){            /* check if lower on disk */
  155.     if(fptr->mdnempty)wget(fptr);
  156.     if(!fptr->mdneof){
  157.         if((cf=strcmp(fptr->mdnbuf->b_key,lowest->b_key))<0){
  158.             flag++;
  159.             lowest=fptr;    /* lowest key */
  160.             }
  161.         else if(cf==0&&fptr->mdnbuf->b_ref<lowest->b_ref){
  162.             flag++;
  163.             lowest=fptr;    /* lowest ref on equal keys */
  164.             }
  165.         }
  166.     fptr=fptr->mdnnext;
  167.     }
  168.     if(flag){
  169.     lowest->mdnempty=1;
  170.     return (lowest->mdnbuf);
  171.     }
  172.     return NULL;
  173. }
  174. wget(fptr)                /* get next record & expand */
  175. struct dsk *fptr;
  176. { int reclen;
  177.   char recin[KEYSIZE+2+1];        /* input packed disk record
  178.     if(fptr->mdneof)return;
  179.     fptr->mdnempty=0;        /* buffer flagged as filled in case EOF*/
  180.     if(wgetr(fptr,&reclen,2)==EOF)return;    /* get reclen */
  181.     if(wgetr(fptr,recin,reclen)==EOF)return;    /* get record */
  182.     wunpack(fptr->mdnbuf,recin);
  183. }
  184.  
  185. wgetr(fptr,buf,len)            /* read <len> bytes into <buf> */
  186. struct dsk *fptr;
  187. unsigned char *buf;
  188. int len;
  189. { int j;
  190.     while(len--){
  191.     if((j=fgetc(fptr->mdnfile))==EOF){
  192.         fptr->mdneof=1;
  193.         return j;
  194.         }
  195.     *buf++=j;
  196.     }
  197. }
  198.  
  199. wunpack(nk,ok)                         /* get packed key as struct BUFR */
  200. struct BUFR *nk;                       /* return EOF if file end */
  201. char *ok;
  202. { char *wunpackey(), *kp=&nk->b_key;
  203.     ok=wunpackey(ok,kp,CPS);            /* key 1*/
  204.     ok=wunpackey(ok,kp+CPS,CPS);        /* key 2*/
  205.     ok=wunpackey(ok,kp+CPS+CPS,8);        /* key 3 (EOS will be there) */
  206.     kp=&nk->b_ref;                              /* get reference */
  207.     *kp++=*ok++;
  208.     *kp++=*ok++;
  209.     return (0);
  210. }
  211.  
  212. char *wunpackey(kp,k,len)        /* convert key string->fixed length*/
  213. char *kp;            /* buffer in */
  214. char k[];            /* new key */
  215. int len;            /* max length of key */
  216. { int i=0;
  217.     while(*kp)k[i++]=*kp++;    /* move in key */
  218.     while(i<len)k[i++]=' ';    /* pad with spaces to size */
  219.     k[i]='\0';            /* mark end of key (in case last one) */
  220.     return ++kp;
  221. }
  222. wrkill()                    /* kill disk chain  */
  223.  struct dsk *last=NULL, *this=polroot, *temp;
  224.     while (this!=NULL){            /* scan list */
  225.     fclose(this->mdnfile);
  226.     unlink(this->mdnfname);
  227.     temp=this;
  228.     this=this->mdnnext;
  229.     free(temp);
  230.     }
  231.     polcurr=polroot=NULL;
  232. }
  233. #ifdef DEBUG
  234. wtrace(tn,dptr)
  235. char *tn;
  236. struct dsk *dptr;
  237. { printf("%s node [%04x] F %04x %s C %4d Pr %04x Nx %04x Sw %1d %1d %04x\n",
  238.     tn,dptr,
  239.     dptr->mdnfile,dptr->mdnfname,dptr->mdncnt,dptr->mdnprev,
  240.     dptr->mdnnext,dptr->mdnempty,dptr->mdneof,dptr->mdnbuf);
  241. }
  242. #endif
  243.